package com.xxl.vueadmin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xxl.vueadmin.common.Result;
import com.xxl.vueadmin.entity.SysMenu;
import com.xxl.vueadmin.entity.SysRoleMenu;
import com.xxl.vueadmin.entity.dto.SysMenuDto;
import com.xxl.vueadmin.mapper.SysMenuMapper;
import com.xxl.vueadmin.service.ISysMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxl.vueadmin.service.ISysRoleMenuService;
import com.xxl.vueadmin.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xu
 * @since 2021-07-28
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {
    @Autowired
    ISysUserService sysUserService;

    @Autowired
    ISysRoleMenuService roleMenuService;

    @Override
    public List<SysMenuDto> getCurrUserNav(String userId) {
        List<Long> menuIds = baseMapper.getPermsIdByUid(userId);
        List<SysMenu> sysMenus = baseMapper.selectBatchIds(menuIds);
        if(sysMenus == null) {
            return null;
        }
        // 构建菜单树集合
        List<SysMenu> treeMenus = bulidTree(sysMenus);
        // 将菜单树转换成dto
        List<SysMenuDto> menuTreeDto = convert(treeMenus);
        return menuTreeDto;
    }

    /**
     * 查询所有菜单信息
     * @return  List<SysMenuDto>
     */
    @Override
    public List<SysMenu> getTree() {
        List<SysMenu> menuList = baseMapper.selectList(new QueryWrapper<SysMenu>().orderByAsc("ordernum"));
        List<SysMenu> sysMenus = bulidTree(menuList);
        return sysMenus;
    }

    @Override
    public Result removeMenu(String id) {
        // 不存在子菜单时删除
        Integer childCount = baseMapper.selectCount(new QueryWrapper<SysMenu>().eq("parent_id", id));
        if(childCount > 0) {
            return  Result.fail("请先删除子菜单");
        }
        int del = baseMapper.deleteById(id);
        // 删除中间表关联信息
        List<SysRoleMenu> delRoleMenuList = roleMenuService.list(new QueryWrapper<SysRoleMenu>().eq("menu_id", id));
        List<String> delIds = delRoleMenuList.stream().map(item -> item.getMenuId()).collect(Collectors.toList());
        roleMenuService.removeByIds(delIds);
        // 删除缓存
        sysUserService.clearMenuAuthority(id);
        return del >0 ? Result.success("删除成功") : Result.fail("删除失败");
    }

    /**
     * 根据菜单集合构建树
     * @param sysMenus
     * @return
     */
    public List<SysMenu> bulidTree(List<SysMenu> sysMenus) {
        String rootMenu = "0";
        // 遍历根节点下的子节点,并构建子节点
        List<SysMenu> menuTree = sysMenus.stream()
                .filter(firstMenu -> firstMenu.getParentId().equals(rootMenu) )
                .map(menu -> {
                    menu.setChildren(getNode(menu, sysMenus));
                    return menu;
        }).collect(Collectors.toList());
        return menuTree;
    }
    public List<SysMenu> getNode(SysMenu sysMenu, List<SysMenu> sysMenus) {
        // 过滤所有当前节点的子节点
        List<SysMenu> childList = sysMenus.stream()
                .filter(item -> sysMenu.getId().equals(item.getParentId()))
                .map(child -> {
                    child.setChildren(getNode(child, sysMenus));
                    return child;
                })
                .sorted(Comparator.comparing(SysMenu::getOrderNum))
                .collect(Collectors.toList());
        sysMenu.getChildren().addAll(childList);
        return childList;
    }

    /**    * menu转menuDto    */
    private List<SysMenuDto> convert(List<SysMenu> menus) {
        List<SysMenuDto> menuDtos = new ArrayList<>();
        menus.forEach(m -> {
            SysMenuDto dto = new SysMenuDto();
            dto.setId(m.getId());
            dto.setName(m.getPerms());
            dto.setTitle(m.getName());
            dto.setComponent(m.getComponent());
            dto.setIcon(m.getIcon());
            dto.setPath(m.getPath());
            if (m.getChildren().size() > 0) {
                dto.setChildren(convert(m.getChildren()));
            }
            menuDtos.add(dto);
        });
        return menuDtos;
    }
}
